﻿using Framework.Zhaogang.Log.Client.ConfigSection;
using Framework.Zhaogang.Utility.Core.Configuration;
using Newtonsoft.Json;
using System;
using System.Configuration;
using System.Dynamic;
using System.Linq;
using System.Net;
using System.Net.Sockets;

namespace Framework.Zhaogang.Log.Client
{
    /// <summary>
    /// 日志操作类
    /// </summary>
    public class Logger : ILog
    {

        #region Ctors

        static Logger()
        {
            logger = new Logger();
            var ipHostEntry = Dns.GetHostEntry(Dns.GetHostName());
            var address = ipHostEntry.AddressList.FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork);
            localIpAddress = address == null ? string.Empty : address.ToString();
            appId = ConfigurationManager.AppSettings["AppId"] ?? "00000";
        }

        #endregion

        #region Fields

        static Logger logger;

        /// <summary>
        /// 本机IPv4地址
        /// </summary>
        static string localIpAddress;

        /// <summary>
        /// 应用号
        /// </summary>
        static string appId;

        #endregion

        #region Methods

        /// <summary>
        /// 创建日志操作器
        /// </summary>
        /// <returns></returns>
        public static Logger CreateLogger()
        {
            return logger;
        }

        /// <summary>
        /// 写入Debug
        /// </summary>
        /// <param name="className"></param>
        /// <param name="methodName"></param>
        /// <param name="content"></param>
        public void Debug(string className, string methodName, dynamic content)
        {
            Type type = content.GetType();
            WriteAppLog(LogLevelTypeEnum.Debug, className, methodName, (type.IsPrimitive || type == typeof(string)) ? content.ToString() : JsonConvert.SerializeObject(content));
        }

        /// <summary>
        /// 写入Info
        /// </summary>
        /// <param name="area"></param>
        /// <param name="title"></param>
        /// <param name="content"></param>
        public void Info(string area, string title, dynamic content)
        {
            Type type = content.GetType();
            WriteAppLog(LogLevelTypeEnum.Info, area, title, (type.IsPrimitive || type == typeof(string)) ? content.ToString() : JsonConvert.SerializeObject(content));
        }

        /// <summary>
        /// 写入Event
        /// </summary>
        /// <param name="area"></param>
        /// <param name="title"></param>
        /// <param name="content"></param>
        public void Event(string area, string title, dynamic content)
        {
            Type type = content.GetType();
            WriteAppLog(LogLevelTypeEnum.Event, area, title, (type.IsPrimitive || type == typeof(string)) ? content.ToString() : JsonConvert.SerializeObject(content));
        }

        /// <summary>
        /// 写入异常
        /// </summary>
        /// <param name="exception"></param>
        public void Error(Exception exception)
        {
            dynamic eoException = new ExpandoObject();
            eoException.Message = exception.Message;
            eoException.Source = exception.Source;
            eoException.StackTrace = exception.StackTrace;
            var content = string.Empty;
            try
            {
                content = JsonConvert.SerializeObject(exception);
            }
            catch
            {
                content = "序列化exception对象失败。";
            }
            WriteAppLog(LogLevelTypeEnum.Error, exception.TargetSite.DeclaringType.FullName, exception.TargetSite.Name, content);
        }

        /// <summary>
        /// 写入错误
        /// </summary>
        /// <param name="exception"></param>
        public void Fatal(Exception exception)
        {
            dynamic eoException = new ExpandoObject();
            eoException.Message = exception.Message;
            eoException.Source = exception.Source;
            eoException.StackTrace = exception.StackTrace;
            var content = string.Empty;
            try
            {
                content = JsonConvert.SerializeObject(exception);
            }
            catch
            {
                content = "序列化exception对象失败。";
            }
            WriteAppLog(LogLevelTypeEnum.Fatal, exception.TargetSite.DeclaringType.FullName, exception.TargetSite.Name, content);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// 写入应用程序日志
        /// </summary>
        /// <param name="logLevelType"></param>
        /// <param name="className"></param>
        /// <param name="methodName"></param>
        /// <param name="content"></param>
        private static void WriteAppLog(LogLevelTypeEnum logLevelType, string className, string methodName, string content)
        {
            if (ConfigurationSectionHandler<LogSettings>.Settings.IsEnabled)
            {
                dynamic appLog = new ExpandoObject();
                appLog.AppId = appId;
                appLog.ClassName = className;
                appLog.CreatedDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
                appLog.Content = content;
                appLog.Ip = localIpAddress;
                appLog.Level = logLevelType;
                appLog.MethodName = methodName;
                LogQueue.AppLogQueue.Enqueue(appLog);
            }
        }

        #endregion

    }
}
